home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / ab20 / unarced / utilities / system / intuition / shadow / docs / introduction.doc < prev    next >
Encoding:
Text File  |  1995-03-17  |  21.4 KB  |  476 lines

  1.                        Shadow Development Documentation
  2.                             Library Version 4.6
  3.  
  4.                               By David Navas
  5.                          Updated:  09 Feb 1992
  6.  
  7.                       Copyright © 1992 by David Navas
  8.                          with help from Karen Lien
  9.                             All Rights Reserved
  10.  
  11.  
  12.                                 THE PLAN
  13.  
  14.           Basic Concepts
  15.               Navas rants....
  16.           OverView -- Meat and Potatoes
  17.               Resource Tracking calls
  18.               Semaphore calls
  19.               AVLTREE calls
  20.               SLIST calls
  21.               WatchedVariable calls
  22.               Object-Oriented calls
  23.               Init-calls.
  24.  
  25.           Detail -- more information about the following.
  26.               System String Constants
  27.               System Semaphoring
  28.               AVL Trees
  29.               Resource Tracking
  30.                    Global
  31.                         Double Pass -- REMOVE/DESTROY
  32.                    Local
  33.                         Auto Resources.
  34.  
  35.               Object-Oriented System
  36.                    Classes
  37.                    Clusters
  38.                    Objects
  39.                    Composites
  40.                    Metas
  41.               Watched Variables
  42.                    three types
  43.                    usage in Browser
  44.               Method Patching
  45.                    Prioritized
  46.                    Conditional Continue
  47.                    Sane Asynchronous Handling
  48.  
  49.  
  50.  
  51.                               BASIC CONCEPTS
  52.  
  53.           SHADOW is a concurrent-object-oriented addition to AmigaDOS.
  54.      Its principle design goal is to help standardize an extensible
  55.      environment paradigm.  It takes advantage of some of the better
  56.      AmigaDOS facilities (shared memory system, IPC ports, and fast
  57.      context switching) by internally managing much of the inter-task
  58.      communications, resource tracking, and resource allocation.
  59.  
  60.           Traditional object-oriented systems separate function
  61.      interfaces from internal data structures and manage the allocation
  62.      and access of these structures within objects.  SHADOW takes this
  63.      interface separation one step further by uncoupling the method
  64.      invocation from the parameter specification.  It also manages the
  65.      allocation of structures in a transparent manner, allowing the use
  66.      of the faster, hard-coded structure offsets of C structs.
  67.  
  68.           SHADOW was created to solve the problems which I ran into with
  69.      my first programming project -- JazzBench.  That experience taught
  70.      me that the most important thing in a co-operative multi-program
  71.      environment is flexibility.  You need to be able to change the
  72.      behaviour of EVERYTHING -as- -it- -runs-.  This lesson was the
  73.      principle reason behind the initial design of SHADOW, and the result
  74.      of that principle was the entire WatchedVariable construct. To a
  75.      lesser extent, it was also responsible for Patches.
  76.  
  77.           However, that was not the only lesson that was learned.  Trying
  78.      to locate governing control in some kind of super-server was a real
  79.      bust.  Turns out so much information had to cross through that
  80.      server to correctly manage all the resources that the server turns
  81.      into a real bottleneck.  So what I needed was a subsystem which
  82.      effectively dealt with the concurrency and shared resource management
  83.      problems.
  84.  
  85.           The other major subsystem of SHADOW supports the increased use
  86.      of more complicated data structures.  Sounds easy, but there've got
  87.      to be a dozen BinTree functions alone, and that doesn't include
  88.      constant string management and singly-linked, priority lists, etc.
  89.  
  90.  
  91.           This introduction is an attempt to acquaint the reader with
  92.      SHADOW's capabilities and limitations, and to introduce the programming
  93.      paradigm it offers to Amiga programmers.
  94.  
  95.  
  96.  
  97.                                  OVERVIEW
  98.  
  99.           The number of functions in SHADOW is truly daunting.  However,
  100.      only a very few need to be well-understood in order to program SHADOW
  101.      effectively.  These functions fall into about seven categories, which
  102.      we will take up in turn.  The following is an informal introduction
  103.      to familiarize you with the terminology and the pertinent function
  104.      calls in SHADOW.  Confusing terms can (hopefully) be found in
  105.      Glossary.doc.  If they can't by, please let me know what they are.
  106.  
  107.           If instead what you want is an in-depth look at the same
  108.      feature-set, please read the section headed by "DETAIL".
  109.  
  110.  
  111.      RESOURCE TRACKING CALLS
  112.  
  113.           SHADOW gives the programmer the ability to track resources, and
  114.      in fact forces him/her to do so.  Objects are NEVER freed until the
  115.      useCount drops to zero.  Objects are often returned from functions
  116.      as Use()'d, meaning that the programmer needs to specifically tell
  117.      the computer when the resource is no longer needed.  For instance,
  118.      the FindBinNode(), and the DoJazzMethod() call when the METHOD
  119.      returns an object both require the programmer to call DropObject()
  120.      on the returned object.
  121.  
  122.           There are two main functions that do resource tracking --
  123.      UseObject() and DropObject().  One increases the useCount of an
  124.      object, the other decreases it.
  125.  
  126.           So far so good?  Good.
  127.  
  128.           There are analogous functions for string constants which are
  129.      useful as well.  I suggest you read the AutoDocs on UseString() and
  130.      DropString().  FindString() is another useful function to understand.
  131.      You should understand that SHADOW keeps string constants on a global
  132.      table, and returns the addresses to these constants on demand.  This
  133.      allows very fast searching of large tables of strings.  You can
  134.      compare the address, rather than the string contents!
  135.  
  136.           All of the other string manipulation calls are based on the
  137.      UseString()/DropString()/FindString() trio.  There is more info
  138.      on system strings below.
  139.  
  140.  
  141.      SEMAPHORES
  142.  
  143.           Semaphores are easy -- there are only two functions -- PSem()
  144.      and VSem().  SHADOW allows you to semaphore any given address with
  145.      the PSem() call, and you can release that semaphore with the VSem()
  146.      call.
  147.  
  148.  
  149.      AVLTREES
  150.  
  151.           Not too tricky yet, eh?
  152.           There are only four really important AVLTREE calls to
  153.      understand:
  154.           AddNodeBinTree() adds an object to an AVL tree sorted by a
  155.                             passed key.
  156.           RemoveBinNode()  removes an object from the AVL tree.
  157.           FindBinNode()    finds the object in an AVL tree, and returns
  158.                             this object.  You should DropObject() that
  159.                             object when you are done using it, as is TRUE
  160.                             of any resource that SHADOW returns to you.
  161.           RecurseBinTree() calls a function for every object in the binary
  162.                             tree.
  163.  
  164.      The other function which is NOT a derivative of these four is
  165.      FreeAllNodesBinTree().  It's a pretty esoteric call -- it just removes
  166.      all objects from the AVL tree, though.  Nothing special.
  167.  
  168.      All other AVL tree calls are derivatives of the first three calls,
  169.      and three other calls [DoPreOrderBinTree() for example] are built
  170.      directly on top of RecurseBinTree() as #defines.
  171.  
  172.  
  173.      SLISTS
  174.  
  175.           Boring, but I'll cover these briefly.  Take a look at these
  176.      functions: AddSListNode(), RemoveSListNode(), and
  177.      FindNodePriInSList().  Guess what they do?  You're almost surely
  178.      correct.
  179.  
  180.  
  181.      WATCHEDVARIABLES
  182.  
  183.           You really want to understand the DIRECTORCLASS for these.  The
  184.      only important function to look at is the WatcherDispatch() function.
  185.      It is responsible for dispatching notification to all interested
  186.      parties.  More information about Watched Variables can be found near
  187.      the end of this document.
  188.  
  189.  
  190.      OBJECT-ORIENTED
  191.  
  192.           You want to be able to look up an attribute in an object, for
  193.      which you use FindAttribute().  Send it the object and the attribute
  194.      name, and it returns the pointer to the attribute in your object.
  195.      Very simple, very straight-forward.
  196.  
  197.           You also want to be able to send off methods, so have a gander
  198.      at DoJazzMethod() -- send it the object, a class (optional), a
  199.      method, the arguments (all optional -- they will default to NULL at
  200.      run-time if left unspecified), and an appended METHOD_END, and you've
  201.      just sent a method.
  202.  
  203.           You'll want to be able to get at public classes as well -- take
  204.      a quick peek at FindInstanceInMeta(), and then realize that
  205.      FindJazzClass() is merely:
  206.           #define FindJazzClass(className) \
  207.                               FindInstanceInMeta(className, METACLASS)
  208.  
  209.           In fact, you may not be surprised to learn that
  210.      FindInstanceInMeta() is just built up from FindString() and
  211.      FindBinNode() [if you've been following me, that is].
  212.  
  213.           Lastly you need some information about creating you're own
  214.      method-functions.  If the examples don't provide enough, I suggest
  215.      you read the AutoDocs describing SetMethodArgs() and
  216.      SetupMethodTags().
  217.  
  218.  
  219.      INIT-CALLS
  220.  
  221.           Last but not least: start your program by opening
  222.      shadow.library, and calling the InitOOProgram() call.  End your
  223.      program by calling RemoveCurrentProgram().
  224.  
  225.  
  226.      That is -IT- folks.  Every other call is either a wrapper, or
  227.      feature-added call that is some kind of variation on these calls,
  228.      or a function which you will almost certainly not need.
  229.  
  230.      Now, of course, you need to understand the methods as well, but
  231.      you've got a handy-dandy Browser for that, and a MUCH shorter
  232.      ShadowLibMethods.doc file too.
  233.  
  234.  
  235.  
  236.                                   DETAIL
  237.  
  238.           This is a more in-depth look at the above features which are
  239.      found in SHADOW.  It starts with simple key concepts like AVL trees,
  240.      system-wide class descriptions and dual-pass Resource Tracking.
  241.      Then it progresses to the more complex topics of watched variables
  242.      and method patching.
  243.  
  244.  
  245.      SYSTEM STRING CONSTANTS
  246.  
  247.           SHADOW uses the concept of unique strings as borrowed from the
  248.      NeXT platform.  Each string is assigned a unique address by the
  249.      system.  Two or more strings of the same contents have the same
  250.      system address.  This allows the system to find strings faster --
  251.      by comparing the address, rather than the contents.
  252.  
  253.           The implementation is via the UseString/DropString/FindString
  254.      library functions, as well as the QuickUseString and QuickDropString
  255.      functions.  System strings are stored on a 1024 entry hash table
  256.      where collisions are linked by a sorted binary tree.  This table is
  257.      found in ShadowBase->sb_systemStrings.
  258.  
  259.           UseString() will lookup the passed string in the table.  If it
  260.      does not find it, the string is created and stored into the table.
  261.      Otherwise, the object's usecount of the located system string is
  262.      incremented.  The system string's address is then returned.
  263.  
  264.           DropString() will lookup the passed string in the table, and,
  265.      if found, the string's useCount is decremented.  If the usecount has
  266.      dropped to zero, the string object is freed and removed from the
  267.      system string list.
  268.  
  269.           FindString() returns the address of a requested system string,
  270.      if one can be found.  It will not increment the usecount, and
  271.      therefore should only be used as an address, rather than as an
  272.      actual string pointer, as that string may go away unexpectedly
  273.      at any time.
  274.  
  275.           QuickUseString() and QuickDropString() take known system string
  276.      addresses and manually increments or decrements the usecount.  If
  277.      the usecount drops to zero, the normal DropString() is used to
  278.      remove the string from the system.
  279.  
  280.  
  281.      SYSTEM SEMAPHORING
  282.  
  283.           SHADOW maintains a global semaphoring system that allows
  284.      programmers to use the concurrent aspects of its object-oriented
  285.      system.  Any address on the Amiga architecture can be semaphored
  286.      via the PSem() call.  They may be locked as SHARED or EXCLUSIVE in
  287.      the same manner as EXEC's Signal Semaphores.  Please see the
  288.      AutoDocs for ObtainSemaphore() and ObtainSharedSemaphore() for
  289.      more information.  System Semaphores are released by the VSem() call.
  290.  
  291.           These semaphores are used internally by the SList and BinTree
  292.      (AVL tree) management calls.
  293.  
  294.  
  295.      AVL TREES
  296.  
  297.           AVL trees are auto-balancing binary trees.  SHADOW defines its
  298.      BinTrees as AVL trees.  You can find out more about AVL trees by
  299.      referring to the AutoDoc's AddNodeBinTree() function.  All of
  300.      the associated BinTree functions are listed in the SEE ALSO
  301.      section.  It is important to remember that the BinTree code
  302.      does not keep objects sorted by string value, but rather, by the
  303.      associated system string address.
  304.  
  305.           SHADOW keeps object instances on an AVLTREE in the object's
  306.      class, sometimes sorted by the object's name, usually by the
  307.      object's address, depending on how the METHOD_META_INIT is
  308.      passed to the RootClass or RootCluster.  Please see the documentation
  309.      of the Methods for more information.
  310.  
  311.           All of the library functions, including RecurseBinTree(), are
  312.      implemented WITHOUT recursion.  This allows them to use a minimal
  313.      amount of stack space (far less than 256bytes), REGARDLESS of how big
  314.      the tree gets.  The functions do assume an addressable range of 2^32
  315.      power....
  316.  
  317.  
  318.      RESOURCE TRACKING
  319.  
  320.           SHADOW uses a simple usecount resource tracking facility to
  321.      allow objects to be shared between several processes.  However,
  322.      SHADOW defines a dual-pass resource tracking algorithm which allows
  323.      circular references, as long as those circular references are
  324.      removed during the first pass removal mechanism.  The
  325.      METHOD_META_REMOVE is meant to serve as the first pass.  When an
  326.      object receives the METHOD_META_REMOVE message, it should remove all
  327.      circular references, and also remove itself from the system lists --
  328.      usually the ATTR_OBJECTLIST of its class (object->cob_class).
  329.  
  330.           The second pass is the METHOD_META_DESTROY.  This method is
  331.      sent to objects whose usecount has fallen to zero.  The memory
  332.      of that object should be freed, as well as any references that
  333.      object makes to other resources.  DropObject() is responsible
  334.      for sending out the METHOD_META_DESTROY.  The programmer
  335.      should never send out a METHOD_META_DESTROY to an object; he/she is,
  336.      however, required to send the METHOD_META_REMOVE to objects.  In
  337.      addition, DropObject() correctly frees any ClasslessObjects
  338.      (see: struct ClasslessObject) whose usecount falls to zero.
  339.  
  340.           The above refers to the GLOBAL resource tracking facilities.
  341.      SHADOW also provides a LOCAL resource tracking facility, which
  342.      helps to reduce the clean-up code (at the expense of some init
  343.      code).  When a resource is allocated that you want to be
  344.      freed when the process exits, you can pass a pointer to the object
  345.      (must be a SHADOW object!) to the AddAutoResource().
  346.  
  347.           If that resource is later freed by your program, before the
  348.      program actually exits, you can remove the reference to it with
  349.      RemoveAutoResource().  Please see the AutoDocs for more details.
  350.      The example code may also be helpful, although not all of it relies
  351.      on auto-tracked resources.
  352.  
  353.           When the METHOD_META_REMOVE method is sent to your program,
  354.      all resources that were added (via AddAutoResource()) are sent
  355.      a METHOD_META_REMOVE, and are then removed from the resource
  356.      tree.  The RemoveCurrentProgram() sends a METHOD_META_REMOVE to
  357.      your program, for example.
  358.  
  359.  
  360.      OBJECT-ORIENTED SYSTEM
  361.  
  362.           Besides the resource tracking and management library functions
  363.      mentioned above, the other three most useful functions will be
  364.      DoJazzMethod(), FindAttribute() and FindJazzClass().  DoJazzMethod()
  365.      is a wrapper around the library DJM() call, and FindJazzClass() is
  366.      a #define wrapper around the library function FindInstanceInMeta().
  367.      All of these functions deal with the object-oriented system within
  368.      SHADOW.
  369.  
  370.           Methods and Attributes are all implemented using the system
  371.      strings mentioned above.  All methods and attributes are named.
  372.      Their definitions are stored in a qsort()'d array inside of the
  373.      class whose instances make use of them.  Methods can be defined
  374.      to run synchronously to a class of processes, synchronously to a
  375.      particular process, asynchronously on a particular process, or
  376.      asynchronously on a particular process 'B' if and only if the
  377.      current process is not of some subclass of the process 'B'.  Methods
  378.      also resource track the process in which they were defined, so that
  379.      the program that defines a method cannot disappear until all
  380.      references to a method (or, really, its class) disappear.
  381.  
  382.           Attributes are allocated in the order in which they appear in the
  383.      defining AttributeTags:  superclass attributes at the lower offsets,
  384.      subclass attributes at the higher offsets.  Attributes may have
  385.      default values associated with them, which are copied into an object
  386.      during the METHOD_META_CREATE method.  In addition, attributes may
  387.      be Watched -- more info on this can be found below.
  388.  
  389.           Every Object has a class.  Every class is an object.  This
  390.      causes a recursive definition.  Therefore, SHADOW contains the
  391.      notion of Metas, which are classes that describe themselves.
  392.      In SHADOW parlance, every Object has a class, every Class has a meta,
  393.      every Meta can usually be found on the ShadowBase->sb_metaTree.
  394.  
  395.           When Classes are created, usually by calling METHOD_META_SUB on
  396.      some existing Class, they are stored in their associated Metas in
  397.      the ATTR_OBJECTLIST attribute.  Metas, in turn, are stored in
  398.      ShadowBase->sb_metaTree.  To allow easy  access to these fundamental
  399.      building blocks, the library function FindInstanceInMeta() is
  400.      provided, and two useful #defines are found in one of the include
  401.      files -- FindJazzClass() and FindJazzCluster().
  402.  
  403.           Classes are your normal every day types of classes.  Clusters
  404.      are defined by the MetaCluster as a class whose instances contain
  405.      a tree of objects, instead of just one.  The instance of a Cluster
  406.      is referred to as a Composite.
  407.  
  408.  
  409.      WATCHED VARIABLES
  410.  
  411.           SHADOW defines a special kind of variable or attribute --
  412.      the WATCHED variable.  These are variables that allow other
  413.      processes to get notification when the contents of the variable
  414.      change.  There are three types of WatchedVariables, the
  415.      WatchedBinTree, the WatchedSList and the WatchedValue.  The
  416.      WatchedBinTree is an AVL tree with the "watch" extensions added.
  417.      The WatchedSList is a singly-linked list with the "watch"
  418.      extensions, and the WatchedValue is a simple longword with the
  419.      "watch" extensions.
  420.  
  421.           Processes can request notification by creating an instance
  422.      of DIRECTORCLASS and requesting a METHOD_DIRECTOR_ESTABLISH method
  423.      on the created object.  Please refer to the ShadowLibMethods.doc
  424.      for more details on DIRECTORCLASS.
  425.  
  426.           There are two ways to get notification, and the included
  427.      Browser program demonstrates them both:  ClassWatchers and
  428.      ObjectWatchers.  An ObjectWatcher is a director which ESTABLISH's
  429.      a watch over a particular instance.  A ClassWatcher is a director
  430.      which watches a set of attributes.  In particular, it watches one
  431.      attribute in ALL of the instances of a class, and all of the
  432.      instances of all of the subclasses of the class.  You will usually
  433.      work with ObjectWatchers, although if the need arises, ClassWatchers
  434.      are available.
  435.  
  436.           Browser uses ObjectWatchers to maintain a current list of
  437.      the available classes, objects, and number of patches on a method.
  438.      If you add a class while the Browser is showing a list of the classes,
  439.      that list is updated automatically, without the active knowledge of
  440.      the program creating the class!
  441.  
  442.  
  443.      METHOD PATCHING
  444.  
  445.           In addition to watched variables, every method in every class
  446.      defined in SHADOW can be "patched".  Patches are additional
  447.      method descriptions (using the same MethodTag structure used for
  448.      regular methods) which allow for more than one function to be called
  449.      for each method invocation.
  450.           Patches have an associated priority, can automatically block
  451.      patches of lower priority, and can dynamically block patches of
  452.      lower priority based upon the contents of the data register d1 as
  453.      returned by the higher priority patch.  The normal method is
  454.      assigned a priority of zero by the system for these purposes.
  455.      See the AutoDoc DJM() for more details.
  456.           DJM() also has some special case code for handling methods
  457.      which are forced to be asynchronous on some other task so that
  458.      the entire patch "chain" is called asynchronously.
  459.  
  460.  
  461.  
  462.                                 CONCLUSION
  463.  
  464.      And that is all she wrote.  This is a good beginning for
  465.      understanding SHADOW.  If you have been confused, you may want to
  466.      look at both Glossary.doc, and at ShadowLibMethods.doc.  It is a
  467.      lot to swallow in one gulp.
  468.  
  469.      If you have understood all of this -- congratulations!  You've done
  470.      better than I would have.  Try and figure out the source, and contact
  471.      me with cash for your includes and shadow.lib today!
  472.  
  473.                David C. Navas [SHADOW]
  474.                950 Mt. View Dr. #6
  475.                Lafayette, CA 94549
  476.